/*
 * mi_beacon.h
 *
 *	Created on: 17.02.2021
 *		Author: pvvx
 */

#ifndef MI_BEACON_H_
#define MI_BEACON_H_

#define ADV_XIAOMI_UUID16 0xFE95 // 16-bit UUID for Members 0xFE95 Xiaomi Inc.
#define XIAOMI_DEV_VERSION	5

enum {
	XIAOMI_DEV_ID_LYWSDCGQ       = 0x01AA,
	XIAOMI_DEV_ID_CGG1           = 0x0347,
	XIAOMI_DEV_ID_CGG1_ENCRYPTED = 0x0B48,
	XIAOMI_DEV_ID_CGDK2          = 0x066F,
	XIAOMI_DEV_ID_LYWSD02        = 0x045B,
	XIAOMI_DEV_ID_LYWSD03MMC     = 0x055B,
	XIAOMI_DEV_ID_CGD1           = 0x0576,
	XIAOMI_DEV_ID_MHO_C303       = 0x06d3,
	XIAOMI_DEV_ID_MHO_C401       = 0x0387,
	XIAOMI_DEV_ID_JQJCY01YM      = 0x02DF,
	XIAOMI_DEV_ID_HHCCJCY01      = 0x0098,
	XIAOMI_DEV_ID_GCLS002        = 0x03BC,
	XIAOMI_DEV_ID_HHCCPOT002     = 0x015D,
	XIAOMI_DEV_ID_WX08ZM         = 0x040A,
	XIAOMI_DEV_ID_MCCGQ02HL      = 0x098B,
	XIAOMI_DEV_ID_YM_K1501       = 0x0083,
	XIAOMI_DEV_ID_YM_K1501EU     = 0x0113,
	XIAOMI_DEV_ID_V_SK152        = 0x045C,
	XIAOMI_DEV_ID_SJWS01LM       = 0x0863,
	XIAOMI_DEV_ID_MJWSD05MMC     = 0x2832,
	XIAOMI_DEV_ID_MJYD02YL       = 0x07F6,
	XIAOMI_DEV_ID_MJWSD06MMC     = 0x55B5
}XIAOMI_DEV_ID;

#if DEVICE_TYPE == DEVICE_LYWSD03MMC
#define	XIAOMI_DID  XIAOMI_DEV_ID_LYWSD03MMC  	// 0x055B LCD display LYWSD03MMC
#elif (DEVICE_TYPE == DEVICE_MJWSD05MMC) || (DEVICE_TYPE == DEVICE_MJWSD05MMC_EN)
#define	XIAOMI_DID  XIAOMI_DEV_ID_MJWSD05MMC  	// 0x2832 LCD display MJWSD05MMC
#elif DEVICE_TYPE == DEVICE_MHO_C401   	
#define	XIAOMI_DID  XIAOMI_DEV_ID_MHO_C401 		// 0x0387 E-Ink display MHO-C401
#elif DEVICE_TYPE == DEVICE_MHO_C401N
#define	XIAOMI_DID  XIAOMI_DEV_ID_MHO_C401 		// 0x0387 E-Ink display MHO-C401
#elif DEVICE_TYPE == DEVICE_CGG1
#define	XIAOMI_DID  XIAOMI_DEV_ID_CGG1_ENCRYPTED	// 0x0B48 E-Ink display CGG1-M "Qingping Temp & RH Monitor"
#elif DEVICE_TYPE == DEVICE_CGDK2
#define	XIAOMI_DID XIAOMI_DEV_ID_CGDK2 			// 0x066F LCD display "Qingping Temp & RH Monitor Lite"
#elif DEVICE_TYPE == DEVICE_MJWSD06MMC
#define	XIAOMI_DID XIAOMI_DEV_ID_MJWSD06MMC
#else
#define	XIAOMI_DID  XIAOMI_DEV_ID_LYWSD03MMC
#endif

enum { // mijia ble version 5, General events
	XIAOMI_DATA_EV_Base					=0x0000,
	XIAOMI_DATA_EV_Connect				=0x0001,
	XIAOMI_DATA_EV_SimplrPair			=0x0002,
	XIAOMI_DATA_EV_Motion				=0x0003,
	XIAOMI_DATA_EV_KeepAway				=0x0004,
	XIAOMI_DATA_EV_LockObsolete			=0x0005,
	XIAOMI_DATA_EV_FingerPrint			=0x0006,
	XIAOMI_DATA_EV_Door					=0x0007,
	XIAOMI_DATA_EV_Armed				=0x0008,
	XIAOMI_DATA_EV_GestureController	=0x0009,
	XIAOMI_DATA_EV_BodyTemp				=0x000a,
	XIAOMI_DATA_EV_Lock					=0x000b,
	XIAOMI_DATA_EV_Flooding				=0x000c,
	XIAOMI_DATA_EV_Smoke				=0x000d,
	XIAOMI_DATA_EV_Gas					=0x000e,
	XIAOMI_DATA_EV_MovingWithLight		=0x000f, // Someone is moving (with light)
	XIAOMI_DATA_EV_ToothbrushIncident	=0x0010,
	XIAOMI_DATA_EV_CatEyeIncident		=0x0011,
	XIAOMI_DATA_EV_WeighingEvent		=0x0012,
	XIAOMI_DATA_EV_Button				=0x1001
} XIAOMI_DATA_EV;

enum { // mijia ble version 5, General attributes
	XIAOMI_DATA_ID_Sleep				=0x1002,
	XIAOMI_DATA_ID_RSSI					=0x1003,
	XIAOMI_DATA_ID_Temperature			=0x1004,
	XIAOMI_DATA_ID_Humidity				=0x1006,
	XIAOMI_DATA_ID_LightIlluminance		=0x1007,
	XIAOMI_DATA_ID_SoilMoisture			=0x1008,
	XIAOMI_DATA_ID_SoilECvalue			=0x1009,
	XIAOMI_DATA_ID_Power				=0x100A,
	XIAOMI_DATA_ID_TempAndHumidity		=0x100D,
	XIAOMI_DATA_ID_Lock					=0x100E,
	XIAOMI_DATA_ID_Gate					=0x100F,
	XIAOMI_DATA_ID_Formaldehyde			=0x1010,
	XIAOMI_DATA_ID_Bind					=0x1011,
	XIAOMI_DATA_ID_Switch				=0x1012,
	XIAOMI_DATA_ID_RemAmCons			=0x1013, // Remaining amount of consumables
	XIAOMI_DATA_ID_Flooding				=0x1014,
	XIAOMI_DATA_ID_Smoke				=0x1015,
	XIAOMI_DATA_ID_Gas					=0x1016,
	XIAOMI_DATA_ID_NoOneMoves			=0x1017,
	XIAOMI_DATA_ID_LightIntensity		=0x1018,
	XIAOMI_DATA_ID_DoorSensor			=0x1019,
	XIAOMI_DATA_ID_WeightAttributes		=0x101A,
	XIAOMI_DATA_ID_NoOneMovesOverTime	=0x101B, // No one moves over time
	XIAOMI_DATA_ID_SmartPillow			=0x101C
} XIAOMI_DATA_ID;

enum { // mijia ble version 5, Vendor-defined attributes
	XIAOMI_VATR_ID_Count			=0x20e1
} XIAOMI_VATR_ID;


/* Encrypted mi beacon structs */
// UUID for Members 0xFE95 Xiaomi Inc. https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf
// All data little-endian, + https://github.com/pvvx/ATC_MiThermometer/tree/master/InfoMijiaBLE

typedef union _adv_mi_fctrl_t { // Frame Control
	struct __attribute__((packed)) {
		u16 Factory:		1; // reserved text
		u16 Connected:		1; // reserved text
		u16 Central:		1; // Keep
		u16 isEncrypted:	1; // 0: The package is not encrypted; 1: The package is encrypted
		u16 MACInclude:	1; // 0: Does not include the MAC address; 1: includes a fixed MAC address (the MAC address is included for iOS to recognize this device and connect)
		u16 CapabilityInclude:		1; // 0: does not include Capability; 1: includes Capability. Before the device is bound, this bit is forced to 1
		u16 ObjectInclude:	1; // 0: does not contain Object; 1: contains Object
		u16 Mesh:			1; // 0: does not include Mesh; 1: includes Mesh. For standard BLE access products and high security level access, this item is mandatory to 0. This item is mandatory for Mesh access to 1.
		u16 registered:	1; // 0: The device is not bound; 1: The device is registered and bound.
		u16 solicited:		1; // 0: No operation; 1: Request APP to register and bind. It is only valid when the user confirms the pairing by selecting the device on the developer platform, otherwise set to 0. The original name of this item was bindingCfm, and it was renamed to solicited "actively request, solicit" APP for registration and binding
		u16 AuthMode:		2; // 0: old version certification; 1: safety certification; 2: standard certification; 3: reserved
		u16 version:		4; // Version number (currently v5)
	} bit;
	u16	word;	// = 0x3050 Frame ctrl
} adv_mi_fctrl_t; // Frame Control

typedef struct __attribute__((packed)) _adv_mi_head_t {
	u8	size;	// = 27?
	u8	uid;	// = 0x16, 16-bit UUID https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
	u16	UUID;	// = 0xFE95, 16-bit UUID for Members 0xFE95 Xiaomi Inc.
	adv_mi_fctrl_t fctrl;	// Frame Control
	u16	dev_id;		// Device type (enum: XIAOMI_DEV_ID)
	u8	counter;	// 0..0xff Measurement count, Serial number, used for de-duplication, different event or attribute reporting requires different Frame Counter
} adv_mi_head_t, * padv_head_enc_t;

typedef struct __attribute__((packed)) _adv_mi_data_t {
	u16	 id;	// = 0x1004, 0x1006, 0x100a (XIAOMI_DATA_ID)
	u8		 size;
	union {
		s16	 data_i16;
		u16	 data_u16;
		u8	 data_u8;
		struct __attribute__((packed)) {
			u8		battery_level; // 0..100 %
		}t0a;
		struct __attribute__((packed)) {
			s16	temperature; // x0.1 C
			u16	humidity; // x0.1 %
		}t0d;
	};
} adv_mi_data_t, * padv_mi_data_t;

typedef struct __attribute__((packed)) _adv_mi_mac_beacon_t {
	adv_mi_head_t head;
	u8		MAC[6];		// [0] - lo, .. [6] - hi digits
	union {
		adv_mi_data_t data;
		u8 capability;
	};
} adv_mi_mac_beacon_t, * padv_mi_mac_beacon_t;

typedef struct __attribute__((packed)) _adv_mi_no_mac_beacon_t {
	adv_mi_head_t head;
	union {
		adv_mi_data_t data;
		u8 capability;
	};
} adv_mi_no_mac_beacon_t, * padv_mi_no_mac_beacon_t;

typedef struct __attribute__((packed)) _adv_mi_ev1_t {
	adv_mi_head_t head;
	struct {
		u16	 id;	// = XIAOMI_DATA_ID_DoorSensor
		u8	 size;
		u8	 value;
	} data;
} adv_mi_ev1_t, * padv_mi_ev1_t;

typedef struct __attribute__((packed)) _adv_mi_ev2_t {
	adv_mi_head_t head;
	struct {
		u16	 id;	// = XIAOMI_VATR_ID_Count
		u8	 size;
		u32	 value;
	} data;
} adv_mi_ev2_t, * padv_mi_ev2_t;


void mi_beacon_summ(void); // averaging measurements
void mi_data_beacon(void);
void mi_event_beacon(u8 n); // n = RDS_TYPES

#if (DEV_SERVICES & SERVICE_BINDKEY)

typedef struct __attribute__((packed)) _adv_mi_cr_ev1_t {
	adv_mi_head_t head;
	struct {
		u16	 id;	// = XIAOMI_DATA_ID_DoorSensor
		u8	 size;
		u8	 value;
	} data;
	u8	cnt[3];
	u8	mic[4];
} adv_mi_cr_ev1_t, * padv_mi_cr_ev1_t;

typedef struct __attribute__((packed)) _adv_mi_cr_ev2_t {
	adv_mi_head_t head;
	struct {
		u16	 id;	// = XIAOMI_VATR_ID_Count
		u8	 size;
		u32	 value;
	} data;
	u8	cnt[3];
	u8	mic[4];
} adv_mi_cr_ev2_t, * padv_mi_cr_ev2_t;



void mi_beacon_init(void);
void mi_encrypt_data_beacon(void);
void mi_encrypt_event_beacon(u8 n); // n = RDS_TYPES
#endif

#endif /* MI_BEACON_H_ */
